Creating Http.sys applications with IntraWeb
What is Http.sys?
Http.sys is the Windows kernel-mode device driver which handles Http and Https request in Windows systems. It listens to such requests coming from TCP stack and forwards them to registered applications. These applications generate complete responses to those requests. One such application is w3wp.exe, the working process of IIS itself. Each virtual application created in IIS starts a new w3wp.exe process which registers itself with Http.sys. So, as you can see, when we talk to Http.sys directly and not through IIS we are actually removing one layer of indirection, making the whole process more simple and improving the overall performance.
You can find complete information about Http.sys here: https://docs.microsoft.com/en-us/iis/get-started/introduction-to-iis/introduction-to-iis-architecture
Why is Http.sys so cool?
For various reasons: It is super mega fast, it scales really well, it is simple to manage - much more than IIS, and it works! Besides that, you can have multiple applications running on the same server port (e.g. standard ports 80 and 443) and you can even use the same port used by IIS, meaning that you can actually install your Http.sys IW application on port 80 (or Https standard port 443) even if you have IIS active on that same server! That's really awesome!
It is super fast because Http.sys is a kernel-mode device driver
Do I need IIS to develop or deploy Http.sys IntraWeb applications?
No, absolutely not! You don't even need IIS installed on your development machine! You don't need it installed on the server either!
Is a Http.sys application deployed as a DLL like ISAPI?
No they are not! Http.sys IW applications are stand alone executables (a simple EXE) which should be installed as services. They work exactly the same as IntraWeb applications based on Indy, but they don't use Indy at all.
Does Http.sys have any other external dependency?
Again, no! The only dependency is on http.sys device driver, which is a core part of every Windows operational system. Your EXE just need to be copied to a folder on the server and it is ready to run.
So how does it work?
In a very simplified way:
When your application runs it tells Http.sys that every request with a certain address should be forwared to it so we can process it and respond. Example: Your application wants that every request received in port 8888 having /MyIWApp/ in the URL path should be forwarded to it. So it registers with Http.sys like
http://+8888/MyIWApp/
This is known as "URL reservation". The plus symbol is known as strong wildcard (read more about it here: https://docs.microsoft.com/en-us/sql/reporting-services/install-windows/url-reservation-syntax-ssrs-configuration-manager?view=sql-server-2017)
After URL registration is successful, all requests coming to port 8888 having /MyIWApp/ as URL base will be forwarded to your application. That's exactly what IIS also does under the hood for each application hosted on it.
After receive a new request, your Http.sys IW application will process it just like any other request, generate a response, compress it and write it back, using other Http.sys API functions. Http.sys will take care of the rest, sending it back to the browser. Simple, isn't it?
How can I create a Http.sys IntraWeb application?
All you need to do is:
- From Delphi/C++ Builder IDE, select File - New - Other. Then IntraWeb, IntraWeb Application Wizard
- Then select:
Application Type: StandAlone Application (Http.sys)
Url Base (optional): Your application will use the url base to create the url used as your application address. It has the form: http(s)://yourserver.com/urlbase/
You can set or change Url base later if you wish.
That's it! Just click OK and your application will be created. Build it and it will just work!
Running/debugging it for the first time
If you build the recently created application and run it, it should just work, like any regular IntraWeb stand alone application. However, you might receive an exception like this when debugging it:
As the message shows, some specific functions called by Http.sys applications - e.g. url registration - require administrator privilages. That's why it raises this exception. When running outside Delphi/C++ Builder debugger, if the same happens, you should see something like this:
http://+8888/MyIWApp/ is the URL that is failing to register.
How to solve this? Simple -> Run your Delphi IDE as local administrator.
This is also required when debugging ISAPI applications on IIS (debugging ISAPI is painful sometimes but it is less painful when you run Delphi as local administrator).
Http.sys application options
When inspecting your application's ServerController you will find these new properties:
AddDefaultBinding: Means that your application will register the default URL with Http.sys when it runs (also known as "URL reservation"). The default URL composed by the protocol (http or https), the wildcard (strong or weak) or virtual host name, port and the url base if applicable.
HostWildcard: it might be strong or weak. In a simplified way, strong wildcard means everything coming to that port, doesn't matter the url of the request. A weak wildcard means all requests to that port not captured by other reservations.
VirtualHostNames: You can use VirtualHostNames to create URL reservations using a host name instead of wildcards (strong or weak). For instance: http://myvirtualhostname:8888/MyIWApp/. This way, Http.sys will forward all requests with that exact URL to your application. More than one Virtual Host Name can be provided (comma separated). All other requests coming to port 8888 will not be forwarded to your application (they can be forwarded to a different IW application, to IIS or any other application using Http.sys).
LimitThreadCountInDebug: When True (default) IntraWeb will ignore property ThreadsPerCore (when set) and use a default ThreadsPerCore value = , only when debuggin (i.e. running on Delphi IDE). It makes startup and shutdown of the application slightly faster and more convenient to debug.
ThreadsPerCore: When set (any value greater than zero) IntraWeb will use this value as the number of threads per core when creating threads for Http.sys processes. When not set (i.e. ThreadsPerCore = 0, the default value), IntraWeb will use 16 threads per core. For instance, if the machine has 8 cores, the application will create 128 threads in total. Please notice that when debugging this number can be different (see LimitThreadCountInDebug). This is an average recommended value for this type of application, based on our tests. We recommend that you use the default value, unless you have a good reason to change it.
There is also a new event you can use to configure your Http.sys IW application:
OnBind: You can use OnBind event to set yourself http and https bindings used by your application. Example:
procedure TIWServerController.IWServerControllerBaseBind(const aHttpBindings,
aHttpsBindings: TStrings);
begin
aHttpBindings.Add('http://+:8888/MyIWApp/');
end;
Structure of an Http.sys application project
This is a standard Http.sys application project:
program HttpSysDemo;
uses
IWRtlFix,
IWJclStackTrace,
IWJclDebug,
IWStartHSys,
Unit1 in 'Unit1.pas' ,
ServerController in 'ServerController.pas' ,
UserSessionUnit in 'UserSessionUnit.pas' ;
{$R *.res}
begin
TIWStartHSys.Execute(True);
end.
Please notice unit IWStartHSys.pas is used (instead of IWStart.pas from an Indy server project) and the line TIWStartHSys.Execute() (instead of TIWStart.Execute() from an Indy server project).
Converting an Indy SA into an Http.sys applicationIt is REALLY easy! Your existing IntraWeb 14 SA application can be modified to run as an Http.sys application editing 2 lines in your DPR file!
Follow these simple steps:
1) Replace IWStart unit by IWStartHSys
2) Replace the call to TIWStart.Execute() by TIWStartHSys.Execute()
Build and run your application. Everything should just work, now using Http.sys as the Http server instead of Indy server.
Deployment of Http.sys applications
In general you deploy a Http.sys application just like an Indy IW applicaiton. They should be installed as Windows services using the command line:
YourApplicationName.exe /install
Please notice that you must set to FALSE the aForceUI parameter in TIWStartHSys.Execute() method, just like in:
begin
TIWStartHSys.Execute(False);
end.
Otherwise the a GUI version will be used instead. A GUI version of your application is awsome for debugging, testing and prototyping, but not for deployment in production. Always use the service version!
Where can I find an Http.sys IW demo?
Here is it: https://github.com/Atozed/IntraWeb/tree/master/15/Delphi/HttpSysDemo
This demo has 2 separate applications which share the same port (8888, but you can use any other port) but respond to different addresses (they have different UrlBase properties).It shows one of the key features of Http.sys applications. As you can see, it is as simple as any Indy server application and can be also easily deployed.
See also
General information about Http.sys:
https://docs.microsoft.com/en-us/iis/get-started/introduction-to-iis/introduction-to-iis-architecture
https://docs.microsoft.com/en-us/iis/get-started/introduction-to-iis/introduction-to-iis-architecture#http-request-processing-in-iis
Url reservation:
https://docs.microsoft.com/en-us/sql/reporting-services/install-windows/url-reservation-syntax-ssrs-configuration-manager?view=sql-server-2017
|